package com.nova.hookapplication;


import android.content.ContentValues;
import android.text.TextUtils;

import com.nova.hookapplication.util.WeChatReplyUtils;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class MainXposed implements IXposedHookLoadPackage {

    //本APP包名
    private static final String APP_PACKAGE_NAME = "com.nova.hookapplication";
    //微信包名
    private static final String WECHAT_PAGKAGE_NAME = "com.tencent.mm";
    //微信数据库包名 和 操作方法  (反编译微信)
    private static final String WECHAT_DATABASE_CLASS_PATH = "com.tencent.wcdb.database.SQLiteDatabase";
    private static final String WECHAT_DATABASE_INSERT_METHOD = "insertWithOnConflict";

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        String packageName = lpparam.packageName;
        String processName = lpparam.processName;
        if (APP_PACKAGE_NAME.equals(packageName)) {
            //hook 客户端的app是否已经激活,激活的话更改值为true
            Class<?> classAppUtils = XposedHelpers.findClassIfExists(APP_PACKAGE_NAME + ".util.AppUtils", lpparam.classLoader);
            if (classAppUtils != null) {
                XposedHelpers.findAndHookMethod(classAppUtils, "isModuleActive", XC_MethodReplacement.returnConstant(true));
                XposedBridge.log("hook客户端com.nova.hookapplication.util.AppUtils的isModuleActive方法。");
            }
        }

        if (WECHAT_PAGKAGE_NAME.equals(packageName) || WECHAT_PAGKAGE_NAME.equals(processName)) {
            XposedBridge.log("进入微信进程：" + lpparam.processName + "包名：" + packageName);
            hookDatabaseInsert(lpparam);
        }
    }

    private void hookDatabaseInsert(final XC_LoadPackage.LoadPackageParam lpparam) {
        Class<?> classDatabase = XposedHelpers.findClassIfExists(WECHAT_DATABASE_CLASS_PATH, lpparam.classLoader);
        if (classDatabase == null) {
            XposedBridge.log("hook微信数据库" + WECHAT_DATABASE_CLASS_PATH + "操作,找不到该类");
            return;
        }
        XposedBridge.log("找到微信SQLiteDatabase操作类");
        XposedHelpers.findAndHookMethod(classDatabase, WECHAT_DATABASE_INSERT_METHOD, String.class, String.class, ContentValues.class, int.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//                super.afterHookedMethod(param);

                String tableName = ((String) param.args[0]);
                String nullColumnHack = ((String) param.args[1]);
                ContentValues contentValues = ((ContentValues) param.args[2]);
                int conflictValue = ((int) param.args[3]);
                printInsertLog(tableName, nullColumnHack, contentValues, conflictValue);
                if (TextUtils.isEmpty(tableName) || contentValues == null) {
                    return;
                }
                if ("message".equals(tableName)) {
                    //过滤聊天消息
                    int isSend = (int) contentValues.get("isSend");
                    //说话人id
                    String talker = (String) contentValues.get("talker");
                    //消息内容
                    String content = (String) contentValues.get("content");
                    //收到消息,屏蔽掉自己发送的、群消息、微信公众号消息
                    if (isSend != 1 && !talker.endsWith("@chatroom") && talker.startsWith("gh_")) {
                        WeChatReplyUtils.reply(lpparam, talker, content);
                    }
                }
            }

            @Override
            protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
//                super.beforeHookedMethod(param);
//                XposedBridge.log("微信数据库插入操作beforeHook");
            }
        });

    }

    //输出插入操作日志
    private void printInsertLog(String tableName, String nullColumnHack, ContentValues contentValues, int conflictValue) {
        String[] arrayConflicValues =
                {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
        if (conflictValue < 0 || conflictValue > 5) {
            return;
        }
        XposedBridge.log("Hook数据库insert,table：" + tableName
                + "\n;nullColumnHack：" + nullColumnHack
                + "\n;CONFLICT_VALUES：" + arrayConflicValues[conflictValue]
                + "\n;contentValues:" + contentValues);
    }
}
